﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Linq;

namespace personalplaner.common.controls
{
	/// <summary>
	/// This class uses Attached DependencyProperties to connect 2 grids to make sure that the columns of grid 2 are all the same width as the columns of grid 1
	/// </summary>
	public class DataGridExtensions
	{
		#region WidthChanging Property

		/// <summary>
		/// WidthChanging Attached Dependency Property
		/// This makes shure that no endless loop takes place
		/// </summary>
		public static readonly DependencyProperty WidthChangingProperty =
			DependencyProperty.RegisterAttached("WidthChanging", typeof(bool), typeof(DataGridExtensions),
				new FrameworkPropertyMetadata(false,
					new PropertyChangedCallback(OnWidthChangingChanged)));

		/// <summary>
		/// Gets the WidthChanging property.  This dependency property 
		/// indicates weather the width of the column is already in change.
		/// </summary>
		public static bool GetWidthChanging(DependencyObject d)
		{
			return (bool)d.GetValue(WidthChangingProperty);
		}

		/// <summary>
		/// Sets the WidthChanging property.  This dependency property 
		/// indicates ....
		/// </summary>
		public static void SetWidthChanging(DependencyObject d, bool value)
		{
			d.SetValue(WidthChangingProperty, value);
		}

		/// <summary>
		/// Handles changes to the WidthChanging property.
		/// </summary>
		private static void OnWidthChangingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
		}

		#endregion

		#region Referenced Grid

		/// <summary>
		/// ReferencedGrid Attached Dependency Property
		/// </summary>
		public static readonly DependencyProperty ReferencedGridProperty =
			DependencyProperty.RegisterAttached("ReferencedGrid", typeof(DataGrid), typeof(DataGridExtensions),
				new FrameworkPropertyMetadata((DataGrid)null,
					new PropertyChangedCallback(OnReferencedGridChanged)));

		/// <summary>
		/// Gets the ReferencedGrid property.  This dependency property 
		/// indicates ....
		/// </summary>
		public static DataGrid GetReferencedGrid(DependencyObject d)
		{
			return (DataGrid)d.GetValue(ReferencedGridProperty);
		}

		/// <summary>
		/// Sets the ReferencedGrid property.  This dependency property 
		/// indicates ....
		/// </summary>
		public static void SetReferencedGrid(DependencyObject d, Type value)
		{
			d.SetValue(ReferencedGridProperty, value);
		}

		/// <summary>
		/// Handles changes to the ReferencedGrid property.
		/// </summary>
		private static void OnReferencedGridChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var element = (DataGrid)d;
			var reference = GetReferencedGrid(d);
			if (reference == null)
				throw new InvalidOperationException("You have to specify a element that is a DataGrid");

			var elcnt = (from c in element.Columns where c.Visibility== Visibility.Visible select c).Count();
			var recnt = (from c in reference.Columns where c.Visibility == Visibility.Visible select c).Count();

			if (element.Columns.Count == 0 || reference.Columns.Count == 0)
			{
				Console.WriteLine("Datagrids don't match column count");
				Console.WriteLine(string.Format("DataGrid 1 Counts {0} columns", element.Columns.Count));
				Console.WriteLine(string.Format("DataGrid 2 Counts {0} columns", reference.Columns.Count));
				return;
			}

			if (reference.Visibility != Visibility.Visible)
			{
				Console.WriteLine("Referenced grid is not visible");
				return;
			}

			if (elcnt != recnt && elcnt == 1)
			{
				var last = reference.Columns[reference.Columns.Count - 1];
				var sum = (from c in reference.Columns
				           where c.Visibility == Visibility.Visible && c != last
				           select c).Sum(c => c.ActualWidth);

				var width = element.ActualWidth - sum;

				if (width > 0)
					last.Width = width;
				return;
			}

			for (int i = 0; i < element.Columns.Count; i++)
			{
				var mainCol = element.Columns[i];
				var refCol = reference.Columns[i];

				DataGridColumn.WidthProperty.AddValueChanged(mainCol,
															 delegate
															 {
																 if (GetWidthChanging(d))
																	 return;
																 SetWidthChanging(d, true);
																 refCol.Width = mainCol.Width;
																 SetWidthChanging(d, false);
															 });

				//DataGridColumn.WidthProperty.AddValueChanged(refCol,
				//                                             delegate
				//                                             {
				//                                                 if (GetWidthChanging(d))
				//                                                     return;
				//                                                 SetWidthChanging(d, true);
				//                                                 mainCol.Width = refCol.Width;
				//                                                 SetWidthChanging(d, false);
				//                                             });
				
			}
		}

		#endregion
	}

	public static class DependencyPropertyExtensions
	{
		public static void AddValueChanged(this DependencyProperty property, object sourceObject, EventHandler handler)
		{
			DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(property, property.OwnerType);
			dpd.AddValueChanged(sourceObject, handler);
		}
	}
}
